package ru.amse.baltijsky.javascheme.importer.test;

import ru.amse.baltijsky.javascheme.importer.IImporter;
import static ru.amse.baltijsky.javascheme.importer.test.TestImporterTools.*;
import static ru.amse.baltijsky.javascheme.tree.NodeType.*;
import ru.amse.baltijsky.javascheme.tree.SchemaNode;
import ru.amse.baltijsky.javascheme.tree.SchemaTree;
import ru.amse.baltijsky.javascheme.tree.TranslationUnitNode;

import java.io.IOException;
import java.io.Reader;
import java.util.LinkedList;
import java.util.List;

/**
 * A dumb importer for importing code like {@code MyTest2.java}.
 */
public class SampleImporterTest2 implements IImporter {
    /**
     * Dumb implementation of the loadTree method. Always returns a sample tree for the following code:
     * public void doSomeJob() {
     * }
     * <p/>
     * public void f(int b) {
     * int a = 10;
     * if(a &lt; b) {
     * for(int i = 0; i &lt; a; ++i, --a) {
     * for(int j = 0; j &lt; i; ++j) {
     * if(j == b) {
     * break;
     * }
     * }
     * if(i == 1) {
     * continue;
     * }
     * doSomeJob();
     * }
     * }
     * do {
     * --b;
     * if(b == 1) {
     * b = 3;
     * }
     * System.out.println(b);
     * } while(b > 0);
     * }
     *
     * @param in         ignored
     * @param className
     * @param methodName
     * @return the root of the artificially constructed tree
     */
    public SchemaTree loadTree(Reader in, String className, String methodName) {
        // we'll need a stack to hold the branching nodes (as they have several next nodes, and to set
        // the links properly we have to remember their occurrences)
        List<SchemaNode> branchNodes = new LinkedList<SchemaNode>();

        // create a dumb class and a function to which the code will belong to
        // the root of the resulting tree
        SchemaNode root = new TranslationUnitNode();
        // the node that is being constructed: cur
        SchemaNode cur = createNodeDeeperLevel(CLASS, root, new String[]{"Dumb"});
        cur = createNodeDeeperLevel(METHOD, cur, new String[]{"void f()"});

        // create the code
        cur = createNodeDeeperLevel(ACTION, cur, new String[]{"int a = 10;"});

        cur = createNodeSameLevel(IF, cur, new String[]{"a < b"});
        branchNodes.add(cur);

        cur = createNodeDeeperLevel(FOR, cur, new String[]{"int i = 0; i < a; ++i, --a"});

        cur = createNodeDeeperLevel(FOR, cur, new String[]{"int j = 0; j < i; ++j"});

        cur = createNodeDeeperLevel(IF, cur, new String[]{"j == b"});
        branchNodes.add(cur);

        cur = createNodeDeeperLevel(BREAK, cur, null);
        branchNodes.remove(branchNodes.size() - 1); // finished working with the latter IF,
        //  no next link was set as it's the
        //  last node in the branch.

        cur = createNodeShallowerLevel(2, IF, cur, new String[]{"i == 1"});
        branchNodes.add(cur);

        cur = createNodeDeeperLevel(CONTINUE, cur, null);

        branchNodes.remove(branchNodes.size() - 1);
        cur = createNodeShallowerLevel(1, ACTION, cur, new String[]{"doSomeJob()"});

        cur = createNodeShallowerLevel(2, DO_WHILE, cur, new String[]{"b > 0"});

        cur = createNodeDeeperLevel(ACTION, cur, new String[]{"--b;"});

        cur = createNodeSameLevel(IF, cur, new String[]{"b == 1"});
        branchNodes.add(cur);

        cur = createNodeDeeperLevel(ACTION, cur, new String[]{"b = 3;"});

        branchNodes.remove(branchNodes.size() - 1);
        createNodeShallowerLevel(1, ACTION, cur, new String[]{"System.out.println();"});

        return new SchemaTree(root);
    }

    public SchemaTree[] loadTrees(Reader in) throws IOException {
        return new SchemaTree[0];
    }

    public String[] getClasses(Reader in) throws IOException {
        return new String[0];
    }

    public String[] getMethods(Reader in, String className) throws IOException {
        return new String[0];
    }
}
